home *** CD-ROM | disk | FTP | other *** search
- *\ :ts=8 bk=0
- *
- * ES.asm: A neato star program based on some Euro code (from the group
- * "Absence" I believe).
- *
- * This code came from Portal under the name STARTOY.LZH and
- * was uploaded by Greg Cunningham (author of BaudBandit).
- * The program was disassembled using ReSource 4.16 (from The
- * Puzzle Factory), and modified from there by me.
- *
- * v2.0 Improvements:
- * o Now compatible with the A4000, AA chipset, and v3.0.
- * o Menu button no longer lunches screen.
- * o Completely new point transformation code.
- * o New star rendering code.
- * o Code speed MEGA-improved over European original
- * (so there, nyah, pthbthbpttt!! :-) :-) :-) :-) ).
- * o Much better performance on a plain 68000-based system.
- * o Sine table resolution increased, yielding finer rotation.
- * o Odd angles now supported.
- * o Smarter about overscan.
- * o Parses Workbench ToolTypes.
- *
- * v1.0 Improvements:
- * o No longer Disable()s the world whle running.
- * o Tossed out hard-coded custom copper list; now uses an
- * Intuition screen. (Drag it! Amaze your friends!)
- * o Uses Intuition Window to collect mouse click.
- * o Now *closes* GfxBase.
- * o Clipping improved.
- * o Replaced 800-entry sinetable with 1024-entry table.
- * o Angles and spins now forced to even values.
- * o New, more traditional perspective formula.
- * o Reasonably commented.
- * o Busy-wait for bottom-of-frame replaced with copper
- * interrupt.
- * o New amazing stupendous incredible argument parser.
- * o Code speed improved slightly (!)
- * o Has an ARexx port!!!!!
- *
- * Some dedicated EuroHacker 91??.??
- * Leo L. Schwab (415) 903-9321 9109.12
- * New argument parsing 9205.09
- * New 1024-entry sinetable 9205.09
- * Functional ARexx 9205.10
- * BOF copper interrupt 9205.11
- * 1.1 enhancements completed (unreleased) 9210.11
- * Workbench ToolTypes added, parser bug fixed 9210.18
- */
-
- ****************************************************************************
- * Documentation.
- *
- ******* ES ******************************************
- *
- * NAME
- * ES -- EuroStars
- *
- * SYNOPSIS
- * ES [MRS][XYZ] <value> [<value> ... ]
- * ES B
- * ES Q (ARexx only)
- *
- * DESCRIPTION
- * ES is a starfield program based on European code that has been
- * massively cleaned up and featurized. As a result, it doesn't run
- * quite as smoothly on vanilla 68000-based systems, but it's less
- * likely to trash your system.
- *
- * ES may be run from the command line or from the Workbench. When
- * you're finished looking, click either mouse button anywhere on the
- * starfield to exit.
- *
- * ES lets you specify how the stars move and rotate. This is done
- * from the command line, Workbench ToolTypes, or from the ARexx port.
- * For all, the argument syntax is the same.
- *
- * ARGUMENTS
- * The M, R, and S operators specify star movement, rotation, and spin
- * respectively. Movement specifies how many world units the stars are
- * translated each frame. Rotation specifies a static/initial rotation
- * angle. Spin specifies the change in rotation for each frame. The
- * X, Y, and Z specifiers indicate which axes the operators are to
- * apply. Rotation angles are specified in "EuroHackerGrads." There
- * are 2048 EHG to a full 360 degree circle.
- *
- * The MRS operators must appear before the the XYZ specifiers, and
- * there may be no spaces between them. Only one MRS operator may
- * appear before a given set of XYZ specifiers. Following the MRSXYZ
- * command are the actual values to be used.
- *
- * It's much easier to understand if you look at the examples.
- *
- * In addition to the above, there are two additional arguments that
- * may be used:
- *
- * B: Operate as background server.
- * Ordinarily, ES will exit when you click on its screen.
- * However, if you want to do extensive ARexx operations
- * without user interference, this option may be specified,
- * causing ES to ignore all subsequent mouse events on its
- * screen. Once backgrounded, ES cannot be un-backgrounded.
- * The only way to terminate a backgrounded ES is with the
- * following command:
- *
- * Q: Quit.
- * When sent as an ARexx command, ES will exit immediately.
- * This option on the CLI command line is meaningless; if
- * present, the entire command line is ignored.
- *
- * WORKBENCH
- * ES recognizes Workbench ToolTypes when started from Workbench. The
- * ToolType strings are identical to the command line arguments.
- * Multiple ToolType strings may be present in the icon; each one will
- * be processed in turn. Project icons and multiple icon selection are
- * also supported; thus, you can have several "canned" starfields ready
- * to go from a Workbench window.
- *
- * Like ARexx commands (see below), the effect of multiple command
- * strings is cumulative.
- *
- * AREXX
- * ES features an ARexx port. The name of the port is EUROSTARS.
- * Commands sent to this port are exactly the same as arguments on the
- * command line. Malformed commands are returned with RC set to
- * RC_ERROR (10).
- *
- * Commands are cumulative; that is, a move command (for example)
- * remains in effect until reset by another move command for the same
- * axis. Thus, an MX command followed later by an SX command does not
- * cancel the MX command.
- *
- * EXAMPLES
- * ES mx 4
- * Move stars 4 units along X axis each frame.
- * ES sxyz 2 -4 6
- * For each frame, spin the X axis 2 EHG, the Y axis -4 EHG,
- * and the Z axis 6 EHG.
- * ES rx 512
- * Rotate X axis 512 EHG and keep it there.
- * ES rx -512 sx 2
- * Start X axis rotated at -512 EHG and add 2 EHG to it each
- * frame.
- * ES mxz 10 0 sxyz 1 1 1
- * Move 10 units along X, zero units along Z, and spin all axes
- * by one EHG each frame.
- * ES mxz sxyz 10 0 1 1 1
- * Identical to the above.
- * ES sxmxsymzsz 1 10 1 0 1
- * Again, identical to the above.
- *
- * As you can see, the syntax is very flexible.
- *
- * NOTES
- * Despite its nomenclature, the 'B' option does not fork ES into the
- * background; you must use the 'Run' command.
- *
- * The coordinate system is right-handed, X axis horizontal, Y axis
- * vertical, Z axis perpendicular to the screen. Positive rotations
- * are clockwise, and are in Z,Y,X order.
- *
- * The default startup values are:
- * MX 0 MY 0 MZ 4 RX 0 RY 0 RZ 0 SX 0 SY 0 SZ 0
- *
- * BUGS
- * Though vastly improved for v2.0, it's still a bit slow on 68000-
- * based systems.
- *
- * Malformed commands generate a diagnostic string to the CLI. These
- * strings are not available to ARexx programs or if the program is
- * started from Workbench. The latter can be particularly annoying, as
- * malformed ToolType strings will cause ES to silently refuse to
- * start. Sigh...
- *
- * AUTHOR
- * Leo L. Schwab -- New Technologies Group, Inc.
- * BIX: ewhac
- * Portal: ewhac
- * InterNet: ewhac@ntg.com ..or.. ewhac@well.sf.ca.us
- *
- ****************************************************************************
- * Includes.
- *
- include 'exec/types.i'
- include 'exec/memory.i'
- include 'graphics/gfxbase.i'
- include 'hardware/intbits.i'
- include 'intuition/intuition.i'
- include 'libraries/dosextens.i'
- include 'workbench/startup.i'
- include 'workbench/workbench.i'
- include 'rexx/storage.i'
- include 'rexx/errors.i'
-
-
- ****************************************************************************
- * A couple of simple macros.
- *
- xlib MACRO
- XREF _LVO\1
- ENDM
-
- jsrlib MACRO
- jsr _LVO\1(a6)
- ENDM
-
-
- ****************************************************************************
- * External references.
- *
- xlib AllocMem
- xlib FreeMem
- xlib AllocSignal
- xlib FreeSignal
- xlib AddIntServer
- xlib RemIntServer
- xlib OpenLibrary
- xlib CloseLibrary
- xlib Forbid
- xlib Permit
- xlib WaitPort
- xlib PutMsg
- xlib GetMsg
- xlib ReplyMsg
- xlib AddPort
- xlib RemPort
- xlib FindTask
- xlib Signal
- xlib Wait
- xlib OpenScreen
- xlib OpenWindow
- xlib CloseScreen
- xlib CloseWindow
- xlib SetPointer
- xlib MakeScreen
- xlib GetScreenData
- xlib RethinkDisplay
- xlib QueryOverscan
- xlib LoadRGB4
- xlib FreeCopList
- xlib UCopperListInit
- xlib CWait
- xlib CMove
- xlib CBump
- xlib Output
- xlib Write
- xlib CreateProc
- xlib Lock
- xlib CurrentDir
- xlib GetDiskObject
- xlib FreeDiskObject
-
- xref _intreq
-
-
- ****************************************************************************
- * Public symbols (primarily for debugging).
- *
- xdef eventloop
- xdef Transform
- xdef NextStar
- xdef GenMat
- xdef StarSeg
- xdef MoveStars
- xdef DrawStars
- xdef SinCos
- xdef ParseArgs
- xdef delta_x
- xdef Matrix
- xdef Screen1_3
- xdef Screen2_0
-
-
- ****************************************************************************
- * Symbol Definitions
- *
- MINBOX equ -450
- MAXBOX equ 450
- BOXRANGE equ MAXBOX-MINBOX+1
-
- NSTARS equ 70 ; Must be even
-
- MAGIC equ (256<<8)
- ZPULL equ 780
-
- SPRBUFSIZ equ 12
-
-
- ****************************************************************************
- * And now for the code!
- *
- section EuroStars,code
-
- CreatedSix ; Hi, Stan!
- bsr ClearBSS ; Initialize uninitialized data
-
- moveq #0,d7 ; No error
- move.l a0,a2 ; Save CLI command line data
- move.l d0,d2
-
- ;------ Open DOS.
- move.l (4).w,a6
- lea DOSName(pc),a1
- moveq #0,d0
- jsrlib OpenLibrary
- move.l d0,DOSBase
- beq err_dos
-
- ;------ Test CLI vs. Workbench.
- sub.l a1,a1 ; Find ourselves
- jsrlib FindTask
- move.l d0,mpsigtask
- move.l d0,a0
- tst.l pr_CLI(a0) ; Are we a CLI?
- beq.s WBench ; No, don't parse command line.
-
- ;------ CLI startup. Parse arguments.
- move.l a2,a0 ; Restore CLI command data
- clr.b 0(a0,d2.l) ; Force NULL at end of command line
- bsr ParseArgs
- bra.s errcheck
-
- ;------ Workbench startup. Get startup message.
- WBench lea pr_MsgPort(a0),a2
- move.l a2,a0
- jsrlib WaitPort
- move.l a2,a0
- jsrlib GetMsg
- move.l d0,WBStartMsg
- bsr ParseWBArgs
-
- ;------ Now then, did the parser return an error?
- errcheck tst.l d0
- ble.s 1$ ; (Ignore 'QUIT')
- bsr PrintCLIStr ; Print the error
- bra err_nomemspr ; Exit (closing DOS)
- 1$
- ;------ Allocate memory for blank sprite.
- moveq #SPRBUFSIZ,d0
- move.l #MEMF_CHIP!MEMF_CLEAR,d1
- jsrlib AllocMem
- move.l d0,sprdat
- beq err_nomemspr
-
- ;------ Allocate signal for message port.
- moveq #-1,d0
- jsrlib AllocSignal
- move.b d0,mpsigbit
- bmi err_signal
-
- ;------ Open Graphics
- lea GfxName(pc),a1
- moveq #0,d0
- jsrlib OpenLibrary
- move.l d0,GBase
- beq err_gfx
-
- ;------ Open Intuition
- lea IntuiName(pc),a1
- moveq #0,d0
- jsrlib OpenLibrary
- move.l d0,IBase
- beq err_intui
-
- ;------ Open screen. This is done differently based on OS version.
- move.l d0,a6
- lea TransformBuff,a3 ; Procure a random buffer...
- cmp.w #37,LIB_VERSION(a6) ; What version?
- blt.s Screen1_3
-
- ;------ Version 2.0. Open OSCAN_MAX screen.
- Screen2_0 move.l a3,a1 ; Use for Rectangle struct
- moveq #OSCAN_MAX,d0
- sub.l a0,a0 ; Zero is LORES_KEY
- jsrlib QueryOverscan
-
- lea scr_def(pc),a0
- move.w ra_MinX(a3),ns_LeftEdge(a0)
- move.w ra_MinY(a3),ns_TopEdge(a0)
- move.w ra_MaxX(a3),d0 ; Yes, this is rather the long
- sub.w ra_MinX(a3),d0 ; way 'round...
- addq.w #1,d0
- move.w ra_MaxY(a3),d1
- sub.w ra_MinY(a3),d1
- addq.w #1,d1
- move.w d0,ns_Width(a0)
- move.w d1,ns_Height(a0)
- asr.w #1,d0
- asr.w #1,d1
- move.w d0,CenterX
- move.w d1,CenterY
-
- jsrlib OpenScreen ; scr_def still in A0
- move.l d0,scrptr
- beq err_scr
- move.l d0,a2
- bra OpenWin
-
- ;------ Version 1.3. Interrogate Workbench screen size.
- Screen1_3 move.l a3,a0 ; Screen buffer
- move.l #sc_SIZEOF,d0 ; bufsiz
- moveq #WBENCHSCREEN,d1 ; Screen type
- sub.l a1,a1 ; NULL
- jsrlib GetScreenData ; Tell me about the Workbench screen
-
- ;------ Scale Workbench dimensions down to lores non-lace pixels.
- move.w sc_ViewPort+vp_DWidth(a3),d0
- btst.b #7,sc_ViewPort+vp_Modes(a3) ; Check HIRES bit
- beq.s 1$ ; HIRES?
- asr.w #1,d0 ; Yes, divide width by two
- 1$ move.w d0,sc_Width(a3)
-
- move.w sc_ViewPort+vp_DHeight(a3),d0
- btst.b #2,sc_ViewPort+vp_Modes+1(a3) ; Check LACE bit
- beq.s 2$ ; LACE?
- asr.w #1,d0 ; Yes, divide height by two
- 2$ move.w d0,sc_Height(a3)
-
- ;------ If Workbench is bigger than us, we upgrade to its size.
- move.w scrwide(pc),d0
- cmp.w sc_Width(a3),d0
- bge.s 3$
- move.w sc_Width(a3),d0
- 3$ move.w d0,scrwide
- asr.w #1,d0
- move.w d0,CenterX
-
- move.w scrhigh(pc),d0
- cmp.w sc_Height(a3),d0
- bge.s 4$
- move.w sc_Height(a3),d0
- 4$ move.w d0,scrhigh
- asr.w #1,d0
- move.w d0,CenterY
-
- ;------ Actually open the Screen.
- lea scr_def(pc),a0
- jsrlib OpenScreen
- move.l d0,scrptr
- beq err_scr
- move.l d0,a2
-
- ;------ Shove screen's ViewPort into nice-ish overscan position
- ;------ based on Workbench screen's size.
- move.w scrwide(pc),d0
- sub.w sc_Width(a3),d0
- asr.w #1,d0 ; Divide difference by two
- sub.w d0,sc_ViewPort+vp_DxOffset(a2) ; Shift screen
-
- move.w scrhigh(pc),d0
- sub.w sc_Height(a3),d0
- asr.w #1,d0
- sub.w d0,sc_ViewPort+vp_DyOffset(a2) ; Shift screen
-
- ;------ Open window on screen.
- OpenWin lea windef(pc),a0
- move.w scrwide(pc),nw_Width(a0)
- move.w scrhigh(pc),nw_Height(a0)
- jsrlib OpenWindow
- move.l d0,winptr
- beq err_win
-
- ;------ Set invisible pointer.
- move.l d0,a0
- move.l sprdat(pc),a1
- moveq #0,d0
- moveq #0,d1
- moveq #0,d2
- moveq #0,d3
- jsrlib SetPointer
-
- ;------ Set local bitplane pointers.
- move.l sc_BitMap+bm_Planes+0(a2),Plane1ptr
- move.l sc_BitMap+bm_Planes+4(a2),Plane2ptr
-
- ;------ Allocate memory for Y offset table.
- moveq #0,d0
- move.w scrhigh(pc),d0
- add.w d0,d0
- moveq #0,d1
- move.l (4).w,a6
- jsrlib AllocMem
- move.l d0,YOffTable
- beq err_nomemtab
-
- bsr GenYOffs
-
- ;------ Add Bottom-of-frame copper interrupt.
- lea MyCopList,a3
- move.l a3,sc_ViewPort+vp_UCopIns(a2) ; vp->UCopIns = cl;
- move.l a3,a0 ; CINIT (cl, 4);
- moveq #4,d0
- move.l GBase(pc),a6
- jsrlib UCopperListInit
-
- move.l a3,a1 ; CWAIT (cl, scrhigh-1, 0);
- moveq #0,d0
- move.w scrhigh(pc),d0
- subq.w #1,d0 ; Back it off just slightly
- moveq #0,d1
- jsrlib CWait
- move.l a3,a1
- jsrlib CBump
-
- move.l a3,a1 ; CMOVE (cl, intreq,
- move.l #_intreq,d0 ; INTF_SETCLR | INTF_COPER);
- move.l #INTF_SETCLR!INTF_COPER,d1
- jsrlib CMove
- move.l a3,a1
- jsrlib CBump
-
- move.l a3,a1 ; CEND (cl);
- move.l #10000,d0
- move.l #255,d1
- jsrlib CWait
- move.l a3,a1 ; Not sure this is necessary, but the
- jsrlib CBump ; gfxmacros.h macro does it...
-
- ;------ Recompose display.
- move.l a2,a0 ; Screen still in A2
- move.l IBase(pc),a6
- jsrlib MakeScreen
- jsrlib RethinkDisplay
-
- ;------ Load colors.
- lea sc_ViewPort(a2),a0
- lea colors(pc),a1
- moveq #4,d0
- move.l GBase(pc),a6
- jsrlib LoadRGB4
-
- ;------ Create sub-process to actually render stars.
- move.l mpsigtask(pc),a0
- moveq #0,d2
- move.b LN_PRI(a0),d2 ; Priority
- subq.l #1,d2 ; (Nudge *BELOW* creator)
- lea StarSeg(pc),a0
- move.l a0,d3 ; SegList pointer
- lsr.l #2,d3 ; (Convert to BPTR)
- lea ESName(pc),a0
- move.l a0,d1 ; Process name
- move.l #4096,d4 ; Stack size
- move.l DOSBase(pc),a6
- jsrlib CreateProc
- move.l d0,d1
- beq err_proc
-
- sub.l #pr_MsgPort,d1 ; Compute address of task
- move.l d1,StarTask ; Store it
-
- ;------ Launch subprocess with startup message.
- move.l d0,a0
- lea startmsg(pc),a1
- move.l (4).w,a6
- jsrlib PutMsg
-
- ;------ Publish message port.
- lea rexxport(pc),a1
- jsrlib AddPort
-
-
- ;------ Wait for ARexx and Intuition events.
- bsr HandleEvents
-
-
- ;------ Remove port and flush all pending messages.
- jsrlib Forbid ; STOP!
- lea rexxport(pc),a2
- move.l a2,a1
- jsrlib RemPort ; Pull port from list
- moveq #RC_FATAL,d2
-
- flushloop move.l a2,a0
- jsrlib GetMsg ; Get message, if any
- tst.l d0
- beq.s 1$ ; No message, leave loop
- move.l d0,a1
- move.l d2,rm_Result1(a1) ; Die die die
- clr.l rm_Result2(a1)
- jsrlib ReplyMsg ; Reply failed message
- bra.s flushloop
- 1$
- jsrlib Permit ; Okay, go ahead.
-
- ;------ Send kill signal to stars process.
- moveq #0,d0
- bset #SIGBREAKB_CTRL_C,d0
- move.l StarTask(pc),a1
- jsrlib Signal
-
- ;------ Wait for startup message to return.
- lea rexxport(pc),a0
- jsrlib WaitPort
-
-
- ;------ Cleanup and exit.
- err_proc move.l GBase(pc),a6 ; Delete UCopList by hand
- move.l scrptr(pc),a0 ; (required for 1.3)
- lea sc_ViewPort+vp_UCopIns(a0),a0
- move.l (a0),a1
- clr.l (a0) ; Keep system from freeing it, too
- move.l ucl_FirstCopList(a1),a0
- jsrlib FreeCopList
-
- move.l (4).w,a6 ; Delete Y Offset table
- move.l YOffTable(pc),a1
- moveq #0,d0
- move.w scrhigh,d0
- add.w d0,d0
- jsrlib FreeMem
- err_nomemtab move.l IBase(pc),a6 ; Close window
- move.l winptr(pc),a0
- jsrlib CloseWindow
- err_win move.l scrptr(pc),a0
- jsrlib CloseScreen
- err_scr move.l a6,a1
- move.l (4).w,a6
- jsrlib CloseLibrary ; Close Intuition
- err_intui move.l GBase(pc),a1
- jsrlib CloseLibrary ; Close Graphics
- err_gfx moveq #0,d0
- move.b mpsigbit(pc),d0
- jsrlib FreeSignal ; Free msgport signal
- err_signal move.l sprdat(pc),a1
- moveq #SPRBUFSIZ,d0
- jsrlib FreeMem
- err_nomemspr move.l DOSBase(pc),a1
- jsrlib CloseLibrary
- err_dos
- move.l WBStartMsg(pc),d0 ; Reply Workbench startup
- beq.s xit ; if present.
-
- jsrlib Forbid ; Prevent Workbench from unloading
- move.l d0,a1 ; us before we've actually exited
- jsrlib ReplyMsg
- clr.l d0
-
- xit rts
-
-
- ****************************************************************************
- * ARexx message and window event processing loop.
- *
- HandleEvents
- ;------ Compute signal flag for window port.
- moveq #0,d2
- move.l winptr(pc),a0
- move.l wd_UserPort(a0),a0
- move.b MP_SIGBIT(a0),d0
- bset.l d0,d2
-
- ;------ Compute signal flag for ARexx port.
- move.b mpsigbit(pc),d0
- bset.l d0,d2
-
- ;------ Wait for something to happen.
- eventloop move.l d2,d0
- jsrlib Wait
-
- ;------ Check for ARexx messages.
- moveq #RC_ERROR,d3
-
- 0$ lea rexxport(pc),a0
- jsrlib GetMsg
- tst.l d0 ; Message present?
- beq.s 9$ ; No, fall off
-
- move.l d0,a2
- move.l ARG0(a2),a0 ; Get argument string
- bsr ParseArgs ; Parse it
- move.l d0,d7 ; Was there an error?
- ble.s 1$ ; No
-
- move.l d3,rm_Result1(a2) ; Yes, store error
- bra.s 2$
-
- 1$ clr.l rm_Result1(a2)
- 2$ clr.l rm_Result2(a2) ; Result2 always NULL
- move.l a2,a1
- jsrlib ReplyMsg ; Send message back
- bra.s 0$ ; Next message, please
- 9$
- ;------ Was that parser return a REXX request for death?
- tst.l d7
- bmi.s Rexxit ; Why, yes it was!
-
- ;------ Check for window events.
- move.l winptr(pc),a0
- move.l wd_UserPort(a0),a0
- jsrlib GetMsg ; Check port
- tst.l d0 ; Something there?
- beq.s eventloop ; No, go to sleep
- move.l d0,a1 ; Yup, reply it
- jsrlib ReplyMsg
-
- ;------ Window event arrived. If we are a background server, ignore
- ;------ the event. Elsewise, return.
- move.w BackServ(pc),d0 ; Just to set flags
- bne.s eventloop
-
- Rexxit rts ; User wants us dead, dammit.
-
-
- ****************************************************************************
- * Welcome to the actual stars code.
- *
- cnop 0,4
-
- StarSeg dc.l 0 ; Phony NextSeg pointer
-
- ;------ Entry point.
- move.l (4).w,a6
- sub.l a1,a1
- jsrlib FindTask ; Get pointer to this task.
- move.l d0,a0
- lea pr_MsgPort(a0),a2 ; Get pointer to MsgPort
-
- ;------ Wait for startup message.
- move.l a2,a0
- jsrlib WaitPort
- move.l a2,a0
- jsrlib GetMsg
- move.l d0,StarMsg
-
- ;------ Compute sigmask.
- moveq #0,d0
- bset.l #SIGBREAKB_CTRL_C,d0
- bset.l #SIGBREAKB_CTRL_F,d0 ; BOF will happen here.
- move.l d0,StarSigMask
-
- ;------ Install interrupt server.
- moveq #INTB_COPER,d0
- lea BOFintrnode(pc),a1
- jsrlib AddIntServer
-
- ;------ Main star loop.
- mainloop bsr AddSpins
- bsr GenMat
- bsr Transform
- bsr.s MoveStars
-
- move.l StarSigMask(pc),d0
- jsrlib Wait ; Wait for BOF or kill signal
- move.l d0,StarSigs
-
- bsr EraseStars ; Do this in any case
- bsr DrawStars
-
- move.l StarSigs(pc),d0
- btst.l #SIGBREAKB_CTRL_C,d0
- beq.s mainloop
-
- ;------ Got kill signal from above. Remove interrupt server,
- ;------ reply startup and exit.
- jsrlib Forbid ; HA! MINE!
- moveq #INTB_COPER,d0
- lea BOFintrnode(pc),a1
- jsrlib RemIntServer
-
- move.l StarMsg(pc),a1
- jmp _LVOReplyMsg(a6) ; Poof! Bye...
-
-
-
- ****************************************************************************
- * Move the stars
- *
- MoveStars lea XCoords(pc),a0
- lea YCoords(pc),a1
- lea ZCoords(pc),a2
- move.w delta_x(pc),d0
- move.w delta_y(pc),d1
- move.w delta_z(pc),d2
- move.w #BOXRANGE,d4
- moveq #NSTARS-1,d7
-
- 0$ move.w (a0),d3
- add.w d0,d3 ; Add move delta
- cmp.w #MAXBOX,d3 ; Too big?
- bgt.s 1$
- cmp.w #MINBOX,d3 ; Too small?
- bge.s 2$
- add.w d4,d3 ; Wrap up
- bra.s 2$
- 1$ sub.w d4,d3 ; Wrap down
- 2$ move.w d3,(a0)+
-
- move.w (a1),d3
- add.w d1,d3
- cmp.w #MAXBOX,d3
- bgt.s 11$
- cmp.w #MINBOX,d3
- bge.s 22$
- add.w d4,d3
- bra.s 22$
- 11$ sub.w d4,d3
- 22$ move.w d3,(a1)+
-
- move.w (a2),d3
- add.w d2,d3
- cmp.w #MAXBOX,d3
- bgt.s 111$
- cmp.w #MINBOX,d3
- bge.s 222$
- add.w d4,d3
- bra.s 222$
- 111$ sub.w d4,d3
- 222$ move.w d3,(a2)+
-
- dbra d7,0$
-
- rts
-
-
- ****************************************************************************
- * Star rendering routines.
- *
- * This too has undergone a re-write since 1.0. A BSET instruction is now
- * used to plot the star directly into the bitmap. The Y-offset into the
- * bitmap is now fetched from a pre-computed table to save on a multiply.
- * A change to the in-memory representation of the projected points saved
- * a few cycles in memory fetches. Further, rendering is now done with bytes
- * rather than words (since BSETs to memory are only byte-wide); any loss on
- * higher-order processors is made up for by the faster clock.
- *
- * EraseStars underwent a kooky change since it appears to be the blocking
- * factor for clean rendering on a 68000. Getting even faster would mean
- * major towering, which falls under the law of diminshing returns.
- *
- EraseStars moveq #0,d0
- move.l Plane1ptr(pc),a1
- move.l Plane2ptr(pc),a2
- lea PlaneOffsets,a4
- moveq #(NSTARS>>1)-1,d7 ; As the programmer :-), I
- ; guarantee the count will be even
-
- 1$ move.l (a4)+,d1 ; Grab two offsets at once
- move.b d0,0(a1,d1.w) ; Blast entire byte
- move.b d0,0(a2,d1.w)
- swap d1 ; Switch to other offset
- move.b d0,0(a1,d1.w) ; Blast entire byte
- move.b d0,0(a2,d1.w)
- dbra d7,1$
-
- rts
-
-
- DrawStars lea TransformBuff,a0 ; Coords in YXZ order
- move.l YOffTable(pc),a1
- lea PlaneOffsets,a3
- move.l Plane1ptr(pc),a2
- move.l Plane2ptr(pc),a4
- moveq #NSTARS-1,d7
- move.w scrhigh(pc),d4
- move.w scrwide(pc),d5
- NextDraw move.w (a0)+,d1 ; Load and check Y value
- bmi.s clipped_y
- cmp.w d4,d1
- bge.s clipped_y
-
- move.w (a0)+,d0 ; Load and check X value
- bmi.s clipped_x
- cmp.w d5,d0
- bge.s clipped_x
-
- move.w d0,d2
- not.w d0 ; Invert X for BSET bit positon
- lsr.w #3,d2 ; Compute byte offset in line
- add.w d1,d1
- move.w 0(a1,d1.w),d1 ; Get Y offset from table
- add.w d1,d2
- move.w d2,(a3)+ ; Store computed offset
- move.w (a0)+,d6 ; Load Z
- cmp.w #-176,d6 ; Z closer than this?
- ble.s 1$ ; No, draw just plane 1 (dim)
-
- bset d0,0(a4,d2.w) ; This plane definitely gets written
- cmp.w #130,d6 ; Very close?
- ble.s 2$ ; No
- 1$ bset d0,0(a2,d2.w) ; Yes; draw brightest value
- 2$
- dbra d7,NextDraw
-
- rts
-
- clipped_y addq.w #2,a0 ; Skip unread x
- clipped_x addq.w #2,a0 ; Skip unread z
- clr.w (a3)+
- dbra d7,NextDraw
-
- rts
-
-
- ****************************************************************************
- * This is the biggie.
- *
- * This has been completely re-written, and where the biggest speed gains
- * were realized. It used to be three discrete rotations. Now it's a full
- * matrix operation.
- *
- * The source XYZ values are loaded into D0-D2. The resulting XYZ values are
- * left in D3-D5. The matrix is stored in column-major ZYX order. This is
- * done to facilitate early rejection of Z values behind the camera (though
- * I don't yet make use of that).
- *
- * The matrix elements are in 2.14 bit fixed-point notation. The numbers in
- * the coordinate array are straight integers.
- *
- Transform lea XCoords(pc),a0
- lea YCoords(pc),a1
- lea ZCoords(pc),a2
- lea TransformBuff,a4
- moveq #NSTARS-1,d7
- move.l #MAGIC,d6
- move.w #ZPULL,a5 ; Being used for storage
-
- ;------ Load vertex and matrix.
- NextStar move.w (a0)+,d0 ; Fetch X, Y, and Z
- move.w (a1)+,d1
- move.w (a2)+,d2
- lea Matrix(pc),a3 ; Fetch matrix
-
- ;------ Multiply vertex through matrix.
- ;------ First column is Z.
- move.w d0,d5 ; X
- muls (a3)+,d5 ; * *mat++
- move.w d1,d4 ; Y
- muls (a3)+,d4 ; * *mat++
- add.l d4,d5 ; Accumulate to D5
- move.w d2,d4 ; Z
- muls (a3)+,d4 ; * *mat++
- add.l d4,d5 ; Accumulate to D5
- swap d5
- rol.l #2,d5 ; D5 >>= 14;
-
- ;------ Second column is Y.
- move.w d0,d4 ; X
- muls (a3)+,d4 ; * *mat++
- move.w d1,d3 ; Y
- muls (a3)+,d3 ; * *mat++
- add.l d3,d4 ; Accumulate to D4
- move.w d2,d3 ; Z
- muls (a3)+,d3 ; * *mat++
- add.l d3,d4 ; Accumulate to D4
- swap d4
- rol.l #2,d4 ; D4 >>= 14;
-
- ;------ Third column is X.
- move.w d0,d3 ; X
- muls (a3)+,d3 ; * *mat++
- move.w d1,d0 ; Y (original X no longer needed)
- muls (a3)+,d0 ; * *mat++
- add.l d0,d3 ; Accumulate to D3
- move.w d2,d0 ; Z
- muls (a3)+,d0 ; * *mat++
- add.l d0,d3 ; Accumulate to D3
- swap d3
- rol.l #2,d3 ; D3 >>= 14;
-
- ****************
- * Here is performed the perspective projection.
- *
- * Normally, this is accomplished by dividing both X and Y by the Z
- * coordinate. However, in this case, only one division is performed to
- * calculate a fixed-point scaling factor, which is then multiplied by the
- * X and Y values. This is done because multiplication is cheaper than
- * division. The perspective scalar is:
- *
- * MAGIC
- * -------------
- * - (Z - ZPULL)
- *
- * The subtraction from Z is to "pull" the stars away from the camera (which
- * is at Z == 0) so that they'll be visible. The negation effectively flips
- * the Z axis, which makes the calculation easier (trust me). MAGIC and
- * ZPULL are currently set to 256 and 780 respectively. The 256 is a number
- * I pulled out of Thin Air. (So's the 780, for that matter...) Feel free
- * to play with them to see what happens.
- *
- * The projected points are stored in YXZ order.
- *
- ;------ Compute scalar.
- move.l d6,d0 ; MAGIC
- move.w a5,d1 ; ZPULL
- sub.w d5,d1 ; - Z
- ble.s BehindCamera
- divu d1,d0 ; == 256 / (ZPULL - Z)
- bvs.s BehindCamera ; Shunt wild division
-
- ;------ Multiply scalar by X and Y components.
- move.w d4,d1 ; Y
- muls d0,d1 ; * 256 / (ZPULL - Z)
- lsr.l #8,d1 ; (Unavoidable. Ack!)
- add.w CenterY(pc),d1
- move.w d1,(a4)+ ; Y store
-
- move.w d3,d1 ; X
- muls d0,d1 ; * 256 / (ZPULL - Z)
- lsr.l #8,d1
- add.w CenterX(pc),d1
- move.w d1,(a4)+ ; X store
-
- move.w d5,(a4)+ ; Z store (for pixel brightness)
-
- dbra d7,NextStar
-
- rts
-
- ;------ Whoops! Behind the camera. Force an invisible point.
- BehindCamera moveq #-1,d1
- move.l d1,(a4)+ ; X and Y store
- move.w d5,(a4)+ ; Z store
- dbra d7,NextStar
-
- rts
-
-
-
- ****************************************************************************
- * Generate a matrix.
- *
- * This routine generates a three-rotation matrix all at once, in ZYX order.
- * Rotations are anti-clockwise.
- *
- GenMat move.w theta_z(pc),d0 ; Collect sines and cosines
- bsr SinCos
- move.w d0,d4 ; sinZ
- move.w d1,d5 ; cosZ
- move.w theta_y(pc),d0
- bsr SinCos
- move.w d0,d2 ; sinY
- move.w d1,d3 ; cosY
- move.w theta_x(pc),d0
- bsr SinCos
-
- lea Matrix(pc),a0 ; Point at matrix
-
- ;------ Compute first column Z.
- ;------ sinX * sinZ - cosX * sinY * cosZ
- move.w d0,d7 ; sinX
- muls d4,d7 ; * sinZ
- move.w d1,d6 ; cosX
- muls d2,d6 ; * sinY
- swap d6
- rol.l #2,d6
- move.w d6,a1 ; (Save for later)
- muls d5,d6 ; * cosZ
- sub.l d6,d7
- swap d7
- rol.l #2,d7 ; D7 >>= 14
- move.w d7,(a0)+ ; (Store)
-
- ;------ sinX * cosZ + cosX * sinY * sinZ
- move.w d0,d6 ; sinX
- muls d5,d6 ; * cosZ
- move.w a1,d7 ; cosX * sinY
- muls d4,d7 ; * sinZ
- add.l d6,d7
- swap d7
- rol.l #2,d7
- move.w d7,(a0)+ ; (Store)
-
- ;------ cosX * cosY
- move.w d1,d7 ; cosX
- muls d3,d7 ; * cosY
- swap d7
- rol.l #2,d7
- move.w d7,(a0)+ ; (Store)
-
- ;------ Compute second column Y.
- ;------ cosX * sinZ + sinX * sinY * cosZ
- move.w d1,d7 ; cosX
- muls d4,d7 ; * sinZ
- move.w d0,d6 ; sinX
- muls d2,d6 ; * sinY
- swap d6
- rol.l #2,d6
- move.w d6,a1 ; (Save for later)
- muls d5,d6 ; * cosZ
- add.l d6,d7
- swap d7
- rol.l #2,d7
- move.w d7,(a0)+ ; (Store)
-
- ;------ cosX * cosZ - sinX * sinY * sinZ
- move.w d1,d7 ; cosX
- muls d5,d7 ; * cosZ
- move.w a1,d6 ; sinX * sinY
- muls d4,d6 ; * sinZ
- sub.l d6,d7
- swap d7
- rol.l #2,d7
- move.w d7,(a0)+ ; (Store)
-
- ;------ -sinX * cosY
- move.w d0,d7 ; sinX
- neg.w d7 ; -
- muls d3,d7 ; * cosY
- swap d7
- rol.l #2,d7
- move.w d7,(a0)+ ; (Store)
-
- ;------ Compute third column X.
- ;------ cosY * cosZ
- move.w d3,d7 ; cosY
- muls d5,d7 ; * cosZ
- swap d7
- rol.l #2,d7
- move.w d7,(a0)+ ; (Store)
-
- ;------ -cosY * sinZ
- move.w d3,d7 ; cosY
- neg.w d7 ; -
- muls d4,d7 ; * sinZ
- swap d7
- rol.l #2,d7
- move.w d7,(a0)+ ; (Store)
-
- ;------ sinY
- move.w d2,(a0)+ ; (Store)
-
- ;------ Phew! We're outa here.
- rts
-
-
- ****************************************************************************
- * Sine/Cosine calculator. Nothing amazing here, just a table lookup.
- *
- * This got a lot more complicated for no good reason :-). The sine/cosine
- * table ranges from 0-90°. The code selects the proper values and negates
- * them based on the quadrant in which the angle lies. 2048 == 360 degrees.
- * Sine table entries are represented using 14 bit fixed point fractions.
- *
- * Angle passed in D0. May now be an odd number.
- * Returns sine in D0, cosine in D1.
- *
- SinCos move.w d2,-(sp)
-
- add.w d0,d0 ; Word offset
- lea SineTable(pc),a5
- move.w d0,d2 ; Copy
- and.w #1024-1,d0 ; Clip to 90°
- move.w #1024,d1 ; d0 == ang
- sub.w d0,d1 ; d1 == gna
-
- move.w 0(a5,d0.w),d0 ; Fetch sine candidate
- move.w 0(a5,d1.w),d1 ; Fetch cosine candidate
-
- ;------ Determine which is sine and which is cosine.
- lsl.w #5,d2 ; Shift quadrant bits into Carry and
- ; Minus flags.
- bpl.s 1$ ; First or third quadrant?
- exg d0,d1 ; Yes, exchange values
- 1$
- ;------ Is sine negative?
- bcc.s 2$ ; Third or fourth quadrants?
- neg.w d0 ; Yes, negate si(g)ne
-
- ;------ Is cosine negative? We test for this two ways, depending on
- ;------ the result of the previous test.
- tst.w d2 ; Quadrant 3?
- bpl.s 88$ ; Yes, negate cosine
- bra.s 99$
-
- 2$ tst.w d2 ; Quadrant 2?
- bpl.s 99$
- 88$ neg.w d1 ; Yes, negate cosine
-
- 99$ move.w (sp)+,d2
- rts
-
-
- ****************************************************************************
- * Add spins to current rotation angles. Clip to 360° circle.
- *
- AddSpins move.w #2048-1,d1 ; 360° == 2048 EHG
- lea theta_x(pc),a0
- lea spin_x(pc),a1
-
- move.w (a0),d0 ; Get angle
- add.w (a1)+,d0 ; Add spin
- and.w d1,d0 ; Clip to 360°
- move.w d0,(a0)+ ; Store it back
-
- move.w (a0),d0
- add.w (a1)+,d0
- and.w d1,d0
- move.w d0,(a0)+
-
- move.w (a0),d0
- add.w (a1),d0
- and.w d1,d0
- move.w d0,(a0)
-
- rts
-
-
-
- ****************************************************************************
- * New ParseArgs. More flexible! Less filling!
- * Added 9202.20 Finished 9205.09
- *
- * A0: Argument string.
- *
- * As the options are parsed, the destination address of the value is
- * pushed on a queue. As values are acquired, the address is pulled,
- * and the value stored there. Imbalances are checked and reported.
- *
- * SYNOPSIS
- * [MRS][XYZ] <value> [ <value> ... ]
- *
- * Only one M, R, or S qualifier may accompany XYZ specifiers. They
- * may be specified in any order, and the values need not immediately
- * follow them.
- *
- * OPTIONS
- * M: Move; specify translation
- * R: Rotate; specify initial rotation
- * S: Spin; specify spin velocities
- *
-
- ParseArgs movem.l d2/d7/a2-a5,-(sp)
- sub.l a3,a3 ; Mode (NULL)
- move.l sp,a4 ; Stacksave
- move.l sp,a5 ; Pop pointer
-
- ;------ Copy active variables to workspace.
- lea delta_x(pc),a1
- lea wrk_delta(pc),a2
- move.l (a1)+,(a2)+
- move.l (a1)+,(a2)+
- move.l (a1)+,(a2)+
- move.l (a1)+,(a2)+
- move.w (a1),(a2)
-
- ;------ Main parsing loop.
- getchar moveq #0,d0
- move.b (a0)+,d0 ; getchar()
- beq EndOfString
- cmp.b #'a',d0 ; Lower case?
- blo.s 0$
- sub.b #'a'-'A',d0 ; Convert to upper case
- 0$
- ;------ Test for whitespace.
- cmp.b #' ',d0
- beq.s whitespace
- cmp.b #9,d0 ; TAB
- beq.s whitespace
- cmp.b #10,d0 ; Newline
- beq.s whitespace
-
- ;------ Test for numeric.
- cmp.b #'-',d0 ; Leading minus
- beq.s numeric
- cmp.b #'0',d0
- blo.s 3$
- cmp.b #'9',d0
- bls.s numeric
- 3$
- ;------ Test for [B]ackground command.
- cmp.b #'B',d0
- bne.s 1$
- move.w d0,BackServ ; All it has to be is non-zero
- bra UnWindOK ; Ignore rest of string
- 1$
- ;------ Test for [Q]uit command.
- cmp.b #'Q',d0
- bne.s 2$
- moveq #-1,d0 ; Tell upstairs we need to quit
- bra UnWind ; Ignore rest of string
- 2$
- ;------ Test for '?' help.
- moveq #ERR_HELP,d7
- cmp.b #'?',d0
- beq ParseError
-
- ;------ Test for 'XYZ'.
- cmp.b #'X',d0
- blo.s 4$
- cmp.b #'Z',d0
- bls.s GotXYZ
- 4$
- ;------ Test for 'MRS'; set mode if present.
- cmp.b #'M',d0
- bne.s 11$
- lea wrk_delta(pc),a3 ; Set mode
- bra.s getchar
- 11$
- cmp.b #'R',d0
- bne.s 22$
- lea wrk_theta(pc),a3 ; Set mode
- bra.s getchar
- 22$
- cmp.b #'S',d0
- bne 33$
- lea wrk_spin(pc),a3 ; Set mode
- bra getchar
- 33$
- ;------ Dunno what this is; error.
- moveq #ERR_SYNTAX,d7
- bra ParseError
-
-
- ;------ Process whitespace.
- whitespace sub.l a3,a3 ; NULL out mode
- bra getchar
-
-
- ;------ Process numerics.
- numeric subq.w #1,a0 ; ungetchar()
- bsr.s GatherNum ; Parsed value returned in D0
-
- moveq #ERR_EXTRAVAL,d7
- cmpa.l sp,a5 ; Are there values yet to be poked?
- beq ParseError ; Nope, too many values.
- move.l -(a5),a1 ; Get address to poke
- move.w d0,(a1) ; Write value.
-
- bra getchar
-
-
- ;------ Process presence of 'XYZ'.
- GotXYZ moveq #ERR_NOMODE,d7
- move.l a3,d1 ; Mode set?
- beq ParseError ; No, user forgot MRS qualifier
-
- sub.b #'X',d0 ; Compute index
- add.w d0,d0 ; Compute word offset
- add.l a3,d0 ; Add "mode" to get final address
- move.l d0,-(sp) ; Push address
- bra getchar
-
-
- ;------ End of string; perform sanity checks and return.
- EndOfString moveq #ERR_MISSINGVAL,d7
- cmpa.l sp,a5 ; Is stack empty?
- bne.s ParseError
-
- ;------ Copy new values to active variables.
- lea wrk_delta(pc),a0
- lea delta_x(pc),a1
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- move.w (a0),(a1)
-
- UnWindOK moveq #0,d0 ; No error
- UnWind move.l a4,sp ; Restore stack pointer
- movem.l (sp)+,d2/d7/a2-a5
- rts ; Back to you, Brian...
-
-
- ****************
- * Gather decimal number.
- *
- GatherNum moveq #0,d0
- moveq #0,d1
- moveq #0,d2 ; negative flag
-
- ;------ Gather chars. Test for whitespace first.
- numloop move.b (a0)+,d1
- beq.s 11$ ; NULL; EOL
- cmp.b #' ',d1
- beq.s 11$
- cmp.b #9,d1 ; TAB
- beq.s 11$
- cmp.b #10,d1 ; Newline
- beq.s 11$
-
- ;------ Check for unary minus.
- cmp.b #'-',d1
- beq.s 22$
-
- ;------ Check for numeric.
- moveq #ERR_BADVAL,d7
- cmp.b #'0',d1
- blo.s ParseError
- cmp.b #'9',d1
- bhi.s ParseError
-
- ;------ Accumulate numeric digit. Overflow not tested.
- mulu #10,d0
- sub.b #'0',d1
- add.w d1,d0
- bra.s numloop
-
- ;------ Flip sense of minus sign. We don't check for multiple
- ;------ instances.
- 22$ not.b d2
- bra.s numloop
-
- ;------ Whitespace encountered; return to parser for storage.
- 11$ tst.b d2 ; This number negative?
- beq.s 110$
- neg.w d0 ; Yep, turn it over
- 110$
- subq.w #1,a0 ; Push back char that stopped us
- rts
-
-
- ****************
- * Short routine to report parsing errors
- *
- ParseError move.l ErrStrs(pc,d7.w),d0 ; Pointer to error string.
- bra.s UnWind
-
-
- ErrStrs dc.l SyntaxErr,BadVal,ModeMissing,MissingVal
- dc.l ExtraVal,HelpStr
-
- ERR_SYNTAX EQU 0
- ERR_BADVAL EQU 4
- ERR_NOMODE EQU 8
- ERR_MISSINGVAL EQU 12
- ERR_EXTRAVAL EQU 16
- ERR_HELP EQU 20
-
-
- ****************************************************************************
- * Parse Workbench icons.
- *
- * This routine scans all icons in the sm_ArgList. Drawer icons are skipped.
- * For each icon, each ToolType string is handed to the parser in turn. If
- * any error is reported, the whole thing aborts and the program won't start
- * (maybe I should throw up a requester someday, eh?)
- *
- ParseWBArgs movem.l d2/d3/d7/a2-a5,-(sp)
- moveq #0,d7 ; Clear error
-
- ;------ Open icon.library.
- lea IconName(pc),a1
- moveq #0,d0
- jsrlib OpenLibrary
- tst.l d0
- beq.s err_noicon
- move.l d0,a6
- move.l DOSBase(pc),a5
-
- ;------ Get WBArg fields.
- move.l WBStartMsg(pc),a2
- move.l sm_NumArgs(a2),d2
- move.l sm_ArgList(a2),a2
-
- ;------ Process each WBArg in turn.
- ArgLoop move.l wa_Name(a2),a3
- tst.b (a3)
- beq.s NextArg ; It's a directory icon, skip it
-
- ;------ CurrentDir() over to icon.
- move.l wa_Lock(a2),d1
- exg a5,a6 ; Get DOSBase
- jsrlib CurrentDir
- exg a5,a6 ; Recover IconBase
- move.l d0,d3 ; Olddir
-
- ;------ Tell me about the icon.
- move.l a3,a0 ; wa_Name
- jsrlib GetDiskObject
- tst.l d0
- beq.s badob ; Failed; ignore it
-
- ;------ Does this icon have any ToolType strings?
- move.l d0,a3
- move.l do_ToolTypes(a3),d0
- beq.s EndStrs ; No ToolType strings, skip it
- move.l d0,a4
-
- ;------ Parse each ToolType string in turn.
- ToolTypeLoop move.l (a4)+,d0
- beq.s EndStrs ; No more strings for this icon
-
- move.l d0,a0 ; String
- bsr ParseArgs
- move.l d0,d7 ; Save error
- beq.s ToolTypeLoop ; No error; keep working
-
- ;------ Drop icon.
- EndStrs move.l a3,a0
- jsrlib FreeDiskObject
-
- ;------ Return to original location.
- badob move.l d3,d1
- exg a5,a6 ; DOSBase
- jsrlib CurrentDir ; Return to original directory
- exg a5,a6 ; IconBase
-
- tst.l d7 ; Was there a parsing error?
- bne.s err_badwbparse ; Yes, abort arg processing
-
- ;------ Advance to next WBArg
- NextArg addq.w #wa_SIZEOF,a2 ; Advance WBArg
- subq.w #1,d2 ; wb_NumArgs--
- bne.s ArgLoop
-
- ;------ Close icon.library.
- err_badwbparse move.l a6,a1
- move.l (4).w,a6
- jsrlib CloseLibrary
-
- err_noicon move.l d7,d0
- movem.l (sp)+,d2/d3/d7/a2-a5
- rts
-
-
- ****************************************************************************
- * Print string to CLI. Pointer to string in D0.
- *
- PrintCLIStr movem.l d2/d3/a2/a6,-(sp)
- move.l d0,a2 ; Save string pointer.
- move.l DOSBase(pc),a6
- jsrlib Output ; Somewhere to print?
- move.l d0,d1
- beq.s 99$ ; No, forget it
-
- move.l a2,d2 ; Compute string length
- 0$ tst.b (a2)+
- bne.s 0$
- suba.l d2,a2
- move.l a2,d3
- subq.l #1,d3
- jsrlib Write ; Write string
- 99$
- movem.l (sp)+,d2/d3/a2/a6
- rts
-
-
- ****************************************************************************
- * Bottom-of-frame interrupt routine.
- *
- BOFintr moveq #0,d0
- bset.l #SIGBREAKB_CTRL_F,d0 ; F stands for Frame
- move.l (4).w,a6
- jsrlib Signal ; Task ptr already in A1
-
- moveq #0,d0
- rts
-
-
- ****************************************************************************
- * Set up the screen Y offset table.
- *
- GenYOffs move.w d2,-(sp)
-
- move.l scrptr(pc),a0
- move.l sc_ViewPort+vp_RasInfo(a0),a0
- move.l ri_BitMap(a0),a0
- move.w bm_BytesPerRow(a0),d1
- move.w bm_Rows(a0),d2
-
- move.l YOffTable(pc),a0
- moveq #0,d0
- subq.w #1,d2 ; Fencepost for DBRA
-
- 1$ move.w d0,(a0)+ ; Write offset
- add.w d1,d0 ; Increment to next row
- dbra d2,1$
-
- move.w (sp)+,d2
- rts
-
-
- ****************************************************************************
- * Something I added to make things more reliable.
- *
- ClearBSS move.l #EndBSS,d2
- lea StartBSS,a2
- sub.l a2,d2
- subq.w #1,d2
- 1$ clr.b (a2)+
- dbra d2,1$
-
- rts
-
-
- ****************************************************************************
- * Data! (Yes, Captain?)
- *
- delta_x dc.w 0 ; Star movement
- delta_y dc.w 0
- delta_z dc.w 4
- theta_x dc.w 0 ; Initial/current rotation angles
- theta_y dc.w 0
- theta_z dc.w 0
- spin_x dc.w 0 ; Spin velocities
- spin_y dc.w 0
- spin_z dc.w 0
-
- wrk_delta dc.w 0,0,0 ; Working areas for the parser
- wrk_theta dc.w 0,0,0
- wrk_spin dc.w 0,0,0
-
- CurrentSinCos dc.w 0 ; theta_x
- dc.w 0
- dc.w 0 ; theta_y
- dc.w 0
- dc.w 0 ; theta_z
- dc.w 0
- Matrix dc.w 0,0,0,0,0,0,0,0,0
- CenterX dc.w 0
- CenterY dc.w 0
- IBase dc.l 0
- GBase dc.l 0
- DOSBase dc.l 0
- winptr dc.l 0
- Plane1ptr dc.l 0
- Plane2ptr dc.l 0
- sprdat dc.l 0
- YOffTable dc.l 0
- WBStartMsg dc.l 0
- StarMsg dc.l 0
- StarSigMask dc.l 0
- StarSigs dc.l 0
- BackServ dc.w 0
-
- XCoords dc.w $FF37,$FED2,$6A,$FFF7,$C8,$CD,$FFF9,$132,$FF35
- dc.w $FF9A,$FF7F,$16B,$EC,$FFF7,$186,$FF5A,$FF0D,$177
- dc.w $FEAF,$6F,$FF5F,$FF22,$150,$2B,$FED5,$FEE3,$90,$AA
- dc.w $FEBE,$13A,$12D,$FFA4,$FF49,$FEEE,$41,$164,$FF09
- dc.w $8A,$FFE3,$D2,$FEBE,$13A,$12D,$FFA4,$FF49,$FEEE,$41
- dc.w $164,$FF09,$8A,$FF46,$FF85,$154,$FF19,$60,$FF5C,$9B
- dc.w $FFA8,$FF18,$158,$AE,$FF2F,$FE72,$21,$8C,$FE8B,$CF
- dc.w $48,$FF7A,$137,$C8,$FED4
- YCoords dc.w $FF5F,$FF22,$150,$2B,$FED5,$FEE3,$90,$AA,$FEBE,$13A
- dc.w $12D,$FFA4,$FF49,$FEEE,$41,$164,$FF09,$8A,$FFE3,$D2
- dc.w $FF37,$FED2,$6A,$FFF7,$C8,$CD,$FFF9,$132,$FF35
- dc.w $FF9A,$FF7F,$16B,$EC,$FFF7,$186,$FF5A,$FF0D,$177
- dc.w $FEAF,$6F,$177,$FEAF,$6F,$FF5F,$FF22,$150,$2B,$FED5
- dc.w $FEE3,$90,$164,$FF09,$8A,$FFE3,$FF52,$FF2F,$18E,$21
- dc.w $FF74,$FE8B,$CF,$FFB8,$86,$FEC9,$D2,$FF22,$94,$14D
- dc.w $FE9B,$F4,$C8,$12C
- ZCoords dc.w $FF52,$FF2F,$FE72,$21,$8C,$175,$FF31,$FFB8,$FF7A
- dc.w $137,11,$153,$FF22,$94,$14D,$FE9B,$F4,$FEEC,$9B
- dc.w $FF46,$FF85,$154,$FF19,$60,$FF5C,$9B,$FFA8,$FF18
- dc.w $158,$FF61,$FE8F,$F8,$FEE7,$8C,$FF85,$48,$FEAC
- dc.w $FF17,$6A,$13B,$FF01,$FF3A,$FFF9,7,$BE,$12B,$FED1
- dc.w $FE94,$FC,$FF91,$CD,$FFF9,$132,$FF35,$FF9A,$FF7F
- dc.w $16B,$EC,$FFF7,$186,$FED2,$6A,$FFF7,$C8,$CD,$FFF9
- dc.w $132,$FF35,$FF9A,$FF7F,$96,$FF06
-
-
- SineTable dc.w 0,50,101,151,201,251,302,352
- dc.w 402,452,503,553,603,653,704,754
- dc.w 804,854,904,955,1005,1055,1105,1155
- dc.w 1205,1255,1306,1356,1406,1456,1506,1556
- dc.w 1606,1656,1706,1756,1806,1856,1906,1956
- dc.w 2006,2055,2105,2155,2205,2255,2305,2354
- dc.w 2404,2454,2503,2553,2603,2652,2702,2752
- dc.w 2801,2851,2900,2949,2999,3048,3098,3147
- dc.w 3196,3246,3295,3344,3393,3442,3492,3541
- dc.w 3590,3639,3688,3737,3786,3835,3883,3932
- dc.w 3981,4030,4078,4127,4176,4224,4273,4321
- dc.w 4370,4418,4467,4515,4563,4612,4660,4708
- dc.w 4756,4804,4852,4900,4948,4996,5044,5092
- dc.w 5139,5187,5235,5282,5330,5377,5425,5472
- dc.w 5520,5567,5614,5661,5708,5756,5803,5850
- dc.w 5897,5943,5990,6037,6084,6130,6177,6223
- dc.w 6270,6316,6363,6409,6455,6501,6547,6593
- dc.w 6639,6685,6731,6777,6823,6868,6914,6960
- dc.w 7005,7050,7096,7141,7186,7231,7276,7321
- dc.w 7366,7411,7456,7501,7545,7590,7635,7679
- dc.w 7723,7768,7812,7856,7900,7944,7988,8032
- dc.w 8076,8119,8163,8207,8250,8293,8337,8380
- dc.w 8423,8466,8509,8552,8595,8638,8680,8723
- dc.w 8765,8808,8850,8892,8935,8977,9019,9061
- dc.w 9102,9144,9186,9227,9269,9310,9352,9393
- dc.w 9434,9475,9516,9557,9598,9638,9679,9720
- dc.w 9760,9800,9841,9881,9921,9961,10001,10040
- dc.w 10080,10120,10159,10198,10238,10277,10316,10355
- dc.w 10394,10433,10471,10510,10549,10587,10625,10663
- dc.w 10702,10740,10778,10815,10853,10891,10928,10966
- dc.w 11003,11040,11077,11114,11151,11188,11224,11261
- dc.w 11297,11334,11370,11406,11442,11478,11514,11550
- dc.w 11585,11621,11656,11691,11727,11762,11797,11831
- dc.w 11866,11901,11935,11970,12004,12038,12072,12106
- dc.w 12140,12173,12207,12240,12274,12307,12340,12373
- dc.w 12406,12439,12472,12504,12537,12569,12601,12633
- dc.w 12665,12697,12729,12760,12792,12823,12854,12885
- dc.w 12916,12947,12978,13008,13039,13069,13100,13130
- dc.w 13160,13190,13219,13249,13279,13308,13337,13366
- dc.w 13395,13424,13453,13482,13510,13538,13567,13595
- dc.w 13623,13651,13678,13706,13733,13761,13788,13815
- dc.w 13842,13869,13896,13922,13949,13975,14001,14027
- dc.w 14053,14079,14104,14130,14155,14181,14206,14231
- dc.w 14256,14280,14305,14329,14354,14378,14402,14426
- dc.w 14449,14473,14497,14520,14543,14566,14589,14612
- dc.w 14635,14657,14680,14702,14724,14746,14768,14789
- dc.w 14811,14832,14854,14875,14896,14917,14937,14958
- dc.w 14978,14999,15019,15039,15059,15078,15098,15118
- dc.w 15137,15156,15175,15194,15213,15231,15250,15268
- dc.w 15286,15304,15322,15340,15357,15375,15392,15409
- dc.w 15426,15443,15460,15476,15493,15509,15525,15541
- dc.w 15557,15573,15588,15604,15619,15634,15649,15664
- dc.w 15679,15693,15707,15722,15736,15750,15763,15777
- dc.w 15791,15804,15817,15830,15843,15856,15868,15881
- dc.w 15893,15905,15917,15929,15941,15952,15964,15975
- dc.w 15986,15997,16008,16018,16029,16039,16049,16059
- dc.w 16069,16079,16088,16098,16107,16116,16125,16134
- dc.w 16143,16151,16160,16168,16176,16184,16192,16199
- dc.w 16207,16214,16221,16228,16235,16242,16248,16255
- dc.w 16261,16267,16273,16279,16284,16290,16295,16300
- dc.w 16305,16310,16315,16319,16324,16328,16332,16336
- dc.w 16340,16343,16347,16350,16353,16356,16359,16362
- dc.w 16364,16367,16369,16371,16373,16375,16376,16378
- dc.w 16379,16380,16381,16382,16383,16383,16384,16384
- dc.w 16384
-
- colors dc.w 0,$336,$669,$CCF
-
- GfxName dc.b 'graphics.library',0
- IntuiName dc.b 'intuition.library',0
- DOSName dc.b 'dos.library',0
- IconName dc.b 'icon.library',0
- ESName dc.b 'EuroStars',0
- ESPortName dc.b 'EUROSTARS',0 ; ARexx wants uppercase. Sigh...
-
-
- ****************
- * Error strings
- *
- SyntaxErr dc.b "Syntax error.",10,0
- BadVal dc.b "Bad value.",10,0
- ModeMissing dc.b "Must specify M, R, or S before XYZ.",10,0
- MissingVal dc.b "Expecting more values.",10,0
- ExtraVal dc.b "Unexpected extra value.",10,0
- dc.b "$VER: "
- HelpStr dc.b "ES 2.0 (18.10.92) -- EuroStars",10
- dc.b "Written by Leo L. Schwab.",10,10
- dc.b "Usage:",10
- dc.b 9,"ES [MRS][XYZ] <value> [<value> ... ]",10
- dc.b 9,"ES B",9,"; Run as background server",10
- dc.b 9,"ES Q",9,"; Quit (ARexx only)",10,10
- dc.b "ARexx port name is EUROSTARS.",10,0
-
-
- ****************
- * Static structure definitions.
- *
- cnop 0,4
-
- ;------ NewScreen
- scr_def dc.w 0,0
- scrwide dc.w 352
- scrhigh dc.w 230
- dc.w 2
- dc.b 0,1
- dc.w 0
- dc.w CUSTOMSCREEN!SCREENQUIET
- dc.l 0
- dc.l ESName
- dc.l 0
- dc.l 0
-
- ;------ NewWindow
- windef dc.w 0,0
- dc.w 352,230
- dc.b -1,-1
- dc.l MOUSEBUTTONS
- dc.l SMART_REFRESH!BACKDROP!BORDERLESS!ACTIVATE!RMBTRAP
- dc.l 0
- dc.l 0
- dc.l 0
- scrptr dc.l 0
- dc.l 0
- dc.w 0,0,0,0
- dc.w CUSTOMSCREEN
-
- ;------ MessagePort
- rexxport dc.l 0,0 ; LN_SUCC, LN_PRED
- dc.b NT_MSGPORT ; LN_TYPE
- dc.b 0 ; LN_PRI
- dc.l ESPortName ; LN_NAME
- dc.b PA_SIGNAL ; MP_FLAGS
- mpsigbit dc.b -1 ; MP_SIGBIT
- mpsigtask dc.l 0 ; MP_SIGTASK
- ds.b LH_SIZE ; MP_MSGLIST,LH_SIZE
-
- ;------ Startup Message
- startmsg dc.l 0,0 ; LN_SUCC, LN_PRED
- dc.b NT_MESSAGE ; LN_TYPE
- dc.b 0 ; LN_PRI
- dc.l ESName ; LN_NAME
- dc.l rexxport ; MN_REPLYPORT
- dc.w MN_SIZE ; MN_LENGTH
-
- ;------ Interrupt structure
- BOFintrnode dc.l 0,0 ; LN_SUCC, LN_PRED
- dc.b NT_INTERRUPT ; LN_TYPE
- dc.b 0 ; LN_PRI
- dc.l ESName ; LN_NAME
- StarTask dc.l 0 ; IS_DATA
- dc.l BOFintr ; IS_CODE
-
-
- ****************************************************************************
- * Uninitialized data
- *
- SECTION EuroStars,BSS
- StartBSS:
-
- MyCopList ds.b ucl_SIZEOF
- TransformBuff ds.w NSTARS*3 ; Written in YXZ order
- PlaneOffsets ds.w NSTARS
-
- EndBSS:
- END
-